<?php
/**
 * ��������� ������� ���������� ��������, �������� ����������� �������������� ������������ url ��������� ������� ������� buildUrl
 *
 * @version 1.0
 * @author ����� �����  * @site http://tovit.livejournal.com/5038.html
 */

class MY_Router extends CI_Router 
{
    const MAIN = 'main';
    const ROUTE = 'route';
    const NAME = 'name';
    const URL = 'url';
	
    /*var $error_controller = 'error';
	var $error_method_404 = 'error_404';
    
 	function My_Router()
    {
        parent::CI_Router();
    }*/
	
    /**
     * Search in Array
     *
     * @param array $arr
     * @param string $key
     * @param string $value
     * @return int index of element
     */
    function _search_by_key(&$arr, $key, $value)
    {
        $ret = false;
        foreach($arr as $k => $v)
        {
            if(!is_int($k)) continue;

            if(is_array($v))
            {
                if($v[$key] == $value)
                {
                    $ret = $k;
                    break;
                }
            }
        }
        return $ret;
    }

	/**
	 *  Parse Routes
	 *
	 * This function matches any routes that may exist in
	 * the config/routes.php file against the URI to
	 * determine if the class/method need to be remapped.
	 *
	 * @access	private
	 * @return	void
	 */
	function _parse_routes()
	{
		// Do we even have any custom routing to deal with?
		// There is a default scaffolding trigger, so we'll look just for 1
		if (count($this->routes) == 1)
		{
			$this->_set_request($this->uri->segments);
			return;
		}

		// Turn the segment array into a URI string
		$uri = implode('/', $this->uri->segments);

		// Is there a literal match?  If so we're done
        if (isset($this->routes[$uri]))
		{
			$this->_set_request(explode('/', $this->routes[$uri]));
			return;
		}

        //Art
        $i = $this->_search_by_key($this->routes, self::MAIN, $uri);
	if ($i !== FALSE)
	{
		$this->_set_request(explode('/', $this->routes[$i][self::ROUTE]));
		return;
	}

	// Loop through the route array looking for wild-cards
	foreach ($this->routes as $key => $val)
	{
            if(is_int($key))
            {
                $key = $val[self::MAIN];
                $val = $val[self::ROUTE];
            }
            // Convert wild-cards to RegEx
            $key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));

            // Does the RegEx match?
            if (preg_match('#^'.$key.'$#', $uri))
            {
                // Do we have a back-reference?
                if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)
                {
                    $val = preg_replace('#^'.$key.'$#', $val, $uri);
                }
                $this->_set_request(explode('/', $val));
                return;
            }
	}

	// If we got this far it means we didn't encounter a
	// matching route so we'll set the site default route
	$this->_set_request($this->uri->segments);
    }


    /**
     * Build the url using params in config by name of rule
     *
     * @param string Name of rule
     * @param array associative array of params
     * @return string url
     */
    function buildUrl($name, $array = null)
    {
        $i = 0;
        $i = $this->_search_by_key($this->routes, self::NAME, $name);
        
        if($i === FALSE)
        {
            log_message('ERROR', 'Try to create undefined url with name: '.$name);
            return $this->config->site_url();
        }

        $rule = $this->routes[$i];
        
        if($array == null){
            return $rule[self::URL];
        }

        //preg_match_all('#^:([a-zA-Z0-9]+)$#', $rule[URL], $m);

        foreach($array as $k => $v)
        {
            $rule[self::URL] = str_replace(':'.$k.'/', $v.'/', $rule[self::URL]);
        }

        return $this->config->site_url($rule[self::URL]);
    } 
    
    /*
	// this is just the same method as in Router.php, with show_404() replaced by $this->error_404();
	function _validate_request($segments)
	{
		// Does the requested controller exist in the root folder?
		if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
		{
			return $segments;
		}
 
		// Is the controller in a sub-folder?
		if (is_dir(APPPATH.'controllers/'.$segments[0]))
		{		
			// Set the directory and remove it from the segment array
			$this->set_directory($segments[0]);
			$segments = array_slice($segments, 1);
 
			if (count($segments) > 0)
			{
				// Does the requested controller exist in the sub-folder?
				if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT))
				{
					return $this->error_404();
				}
			}
			else
			{
				$this->set_class($this->default_controller);
				$this->set_method('index');
 
				// Does the default controller exist in the sub-folder?
				if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT))
				{
					$this->directory = '';
					return array();
				}
			}
 
			return $segments;
		}
 
		// Can't find the requested controller...
		return $this->error_404();
	}
 
	function error_404()
	{
		$this->directory = "";
		$segments = array();
		$segments[] = $this->error_controller;
		$segments[] = $this->error_method_404;
		return $segments;
	}
 
	function fetch_class()
	{
		// if method doesn't exist in class, change
		// class to error and method to error_404
		$this->check_method();
 
		return $this->class;
	}
 
	function check_method()
	{
		$ignore_remap = true;
 
		$class = $this->class;
		if (class_exists($class))
		{	
			// methods for this class
			$class_methods = array_map('strtolower', get_class_methods($class));
 
			// ignore controllers using _remap()
			if($ignore_remap && in_array('_remap', $class_methods))
			{
				return;
			}
 
			if (! in_array(strtolower($this->method), $class_methods))
			{
				$this->directory = "";
				$this->class = $this->error_controller;
				$this->method = $this->error_method_404;
				include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);
			}
		}
	}
 
	function show_404()
	{
		include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);
		call_user_func(array($this->error_controller, $this->error_method_404));
	}*/
    
}
?>